package com.healthcloud.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by xiam on 2015/6/8.
 */
public abstract class AreaCodeUtils {

	public static final int LEVEL_PROVINCE = 1;

	public static final int LEVEL_CITY = 2;

	public static final int LEVEL_COUNTY = 3;

	public static final int LEVEL_TOWN = 4;

	public static final int LEVEL_VILLAGE = 5;

	/**
	 * <p>根据当前地区编码判断地区等级</p>
	 * @param code
	 * @return
	 */
	public static final int getCodeLevel(Long code) {
		if (code == null) {
			return LEVEL_PROVINCE;
		}
		int length = numberLen(code);
		if (length == 12) {
			return LEVEL_VILLAGE;
		}
		if (length == 9) {
			return LEVEL_TOWN;
		}
		if (length == 6) {
			return LEVEL_COUNTY;
		}
		if (length == 4) {
			return LEVEL_CITY;
		}
		if (length == 2) {
			return LEVEL_PROVINCE;
		}
		throw new IllegalArgumentException("Illegal area code: " + code.toString());
	}

	/**
	 * 获取下一级地区编码等级
	 * @param code
	 * @return
	 */
	public static final int getNextCodeLevel(Long code) {
		return getCodeLevel(code) + 1;
	}

	public static final List<Long> getFullCode(Long code) {
		if (code == null) {
			return Collections.emptyList();
		}
		int codeLevel = getCodeLevel(code);
		List<Long> list = new ArrayList<>(3);
		switch (codeLevel) {
		case LEVEL_PROVINCE:
			list.add(code);
			break;
		case LEVEL_CITY:
			list.add(getProvinceCode(code));
			list.add(code);
			break;
		case LEVEL_COUNTY:
			list.add(getProvinceCode(code));
			list.add(getCityCode(code));
			list.add(code);
			break;
		case LEVEL_TOWN:
			list.add(getProvinceCode(code));
			list.add(getCityCode(code));
			list.add(getCountyCode(code));
			list.add(code);
			break;
		case LEVEL_VILLAGE:
			list.add(getProvinceCode(code));
			list.add(getCityCode(code));
			list.add(getCountyCode(code));
			list.add(getTownCode(code));
			list.add(code);
			break;
		default:
			return Collections.emptyList();
		}
		return list;
	}

	/**
	 * 根据当前地区编码, 计算出其所属的省份编码
	 * @param code
	 * @return
	 */
	public static final Long getProvinceCode(Long code) {
		return calculateAreaCode(code, 2, 10000);
	}

	/**
	 * 根据当前的地区编码, 计算出其所属城市的编码
	 * @param code
	 * @return
	 */
	public static final Long getCityCode(Long code) {
		return calculateAreaCode(code, 4, 100);
	}

	/**
	 * 根据当前的地区编码, 计算出其所属县的编码
	 * @param code
	 * @return
	 */
	public static final Long getCountyCode(Long code) {
		return calculateAreaCode(code, 6, 1);
	}

	/**
	 * 根据当前的地区编码, 计算出其所属街道的编码
	 * @param code
	 * @return
	 */
	public static final Long getTownCode(Long code) {
		return calculateAreaCode(code, 9, 1);
	}

	/**
	 * 根据当前的地区编码, 计算出其所属乡镇的编码
	 * @param code
	 * @return
	 */
	public static final Long getVillageCode(Long code) {
		return calculateAreaCode(code, 12, 1);
	}

	/**
	 * 计算地区代码
	 * @param code 给定的地区代码
	 * @param len 截取长度, 省 2 位, 市 4 位, 县 6 位
	 * @param rate 倍率
	 * @return
	 */
	private static final Long calculateAreaCode(Long code, int len, int rate) {
		if (code == null) {
			return null;
		}
		String codeStr = code.toString().substring(0, len); // 获取两位省份代码
		return Long.valueOf(codeStr) * rate;
	}

	/**
	 * <p>
	 * 根据当前地区编码计算出下一级地区的起始范围
	 * </p>
	 *
	 * @param code
	 * @return
	 */
	public static final Long[] getAreaRange(Long code) {
		Long[] range = { 0L, 0L };
		int rate = 0;
		int level = getNextCodeLevel(code);
		if (level > LEVEL_COUNTY) { // 第四级开始，每三位代表一级
			rate = 1000;
		}
		else { // 第四级之前，每两位代表一级
			rate = 100;
		}
		range[0] = code * rate;
		range[1] = range[0] + rate;
		return range;
	}

	/**
	 * <p>
	 * 根据当前地区编码计算出所有级别地区的code
	 * </p>
	 *
	 * @param code
	 * @return codeList
	 * codeList[0]:省code	codeList[1]:市code	codeList[2]:县code	codeList[3]:镇code	codeList[4]:村code
	 */
	public static final Long[] getCodeListAll(Long code){
		Long[] codeArray = { 0L, 0L, 0L, 0L, 0L };
		if (code==null) {
			return codeArray;
		}
		String codeStr = code.toString();
		if (codeStr.length()>=2) {
			codeArray[0] = Long.valueOf(codeStr.substring(0, 2));
		}
		if (codeStr.length()>=4) {
			codeArray[1] = Long.valueOf(codeStr.substring(0, 4));
		}
		if (codeStr.length()>=6) {
			codeArray[2] = Long.valueOf(codeStr.substring(0, 6));
		}
		if (codeStr.length()>=9) {
			codeArray[3] = Long.valueOf(codeStr.substring(0, 9));
		}
		if (codeStr.length()>=12) {
			codeArray[4] = Long.valueOf(codeStr.substring(0, 12));
		}
		return codeArray;
	}

	private static int numberLen(long code) {
		int len = 0;
		for (;;) {
			code = code / 10;
			len++;
			if (code == 0) {
				break;
			}
		}
		return len;
	}
}
